from django.contrib import admin
from django import forms
from django.utils.html import format_html
from django.core.files.storage import default_storage
from datetime import datetime
from django.conf import settings
import os
import hashlib
import urllib.request
import urllib.parse
import json
from .models import Post, PostLike, Comment, Tag, HomeBanner
from django import forms
from backed.cos_utils import cos_uploader


class MultiFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True


class PostAdminForm(forms.ModelForm):
    image = forms.FileField(required=False)

    class Meta:
        model = Post
        fields = ['user', 'content', 'image_urls', 'image']

    def clean_images(self):
        files = self.files.getlist('images') if hasattr(self, 'files') else []
        return files


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """动态管理"""
    list_display = ['post_id', 'user_link', 'display_content', 'display_images', 'image_count', 'like_count', 'comment_count', 'display_location', 'created_at', 'display_actions']
    list_filter = ['created_at', 'city', 'province']
    date_hierarchy = 'created_at'
    search_fields = ['user__username', 'content']
    ordering = ['-created_at']
    list_per_page = 20
    form = PostAdminForm
    change_form_template = 'admin/community/post/change_form.html'
    actions = ['action_reverse_geocode', 'action_clear_location']
    
    # 详情页配置
    fieldsets = [
        ('基本信息', {
            'fields': ['user', 'content', 'tags']
        }),
        ('图片', {
            'fields': ['image', 'image_urls']
        }),
    ]
    
    # 只读字段
    readonly_fields = ['display_images_preview', 'like_count', 'comment_count', 'created_at']
    
    def display_content(self, obj):
        """显示内容摘要"""
        if obj.content:
            content = obj.content
            if len(content) > 50:
                return f"{content[:50]}..."
            return content
        return "无内容"
    display_content.short_description = '内容'
    
    def display_images(self, obj):
        """在列表页显示图片缩略图"""
        return obj.get_image_preview_html(max_images=3, thumbnail_size='50px')
    display_images.short_description = '图片预览'
    
    def display_images_preview(self, obj):
        """在详情页显示完整图片预览"""
        return obj.get_full_image_preview_html()
    display_images_preview.short_description = '图片预览'
    
    def image_count(self, obj):
        """显示图片数量"""
        return obj.get_image_count()
    image_count.short_description = '图片数'

    def display_location(self, obj):
        city = obj.city or '未知城市'
        province = obj.province or '未知省份'
        lat = (f"{obj.lat:.5f}" if obj.lat is not None else '-')
        lng = (f"{obj.lng:.5f}" if obj.lng is not None else '-')
        return f"{province} {city} ({lat}, {lng})"
    display_location.short_description = '位置'
    
    def like_count(self, obj):
        """显示点赞数量"""
        return PostLike.objects.filter(post=obj).count()
    like_count.short_description = '点赞数'
    
    def comment_count(self, obj):
        """显示评论数量"""
        return Comment.objects.filter(post=obj).count()
    comment_count.short_description = '评论数'
    
    def user_link(self, obj):
        """显示用户链接"""
        if obj.user:
            return format_html(
                '<a href="/admin/auth/user/{}/change/">用户 {}</a>',
                obj.user.id, obj.user.username
            )
        return "未设置用户"
    user_link.short_description = '用户'

    def display_actions(self, obj):
        """显示操作按钮"""
        return format_html(
            '<div style="display: flex; gap: 5px;">'
            '<a href="/admin/community/post/{}/change/" class="button" style="padding: 3px 8px; background: #417690; color: white; text-decoration: none; border-radius: 3px; font-size: 12px;">编辑</a>'
            '<a href="/admin/community/post/{}/delete/" class="button" style="padding: 3px 8px; background: #ba2121; color: white; text-decoration: none; border-radius: 3px; font-size: 12px;">删除</a>'
            '</div>',
            obj.post_id, obj.post_id
        )
    display_actions.short_description = '操作'

    def save_model(self, request, obj, form, change):
        uploaded = request.FILES.get('image')
        if uploaded:
            if uploaded.content_type in ['image/jpeg', 'image/png', 'image/gif', 'image/webp'] and uploaded.size <= 10 * 1024 * 1024:
                result = cos_uploader.upload_file(uploaded, file_type='community', user_id=(obj.user.id if obj.user else None))
                if result.get('success'):
                    current = obj.image_urls if isinstance(obj.image_urls, list) else (obj.image_urls or [])
                    if not isinstance(current, list):
                        current = []
                    current.append(result.get('url'))
                    obj.image_urls = current
                else:
                    require_cos = getattr(settings, 'TENCENT_COS_REQUIRE', False)
                    if require_cos:
                        try:
                            self.message_user(request, 'COS未配置或上传失败：未保存图片', level='error')
                        except Exception:
                            pass
                    else:
                        uid = (obj.user.id if obj.user else 'anon')
                        date_folder = datetime.now().strftime('%Y%m%d')
                        rel_path = f"community/user_{uid}/{date_folder}/{uploaded.name}"
                        saved_path = default_storage.save(rel_path.replace('\\', '/'), uploaded)
                        media_url = (getattr(settings, 'MEDIA_URL', '/media/') or '/media/')
                        rel_url = media_url.rstrip('/') + '/' + saved_path.replace('\\', '/')
                        url = request.build_absolute_uri(rel_url)
                        current = obj.image_urls if isinstance(obj.image_urls, list) else (obj.image_urls or [])
                        if not isinstance(current, list):
                            current = []
                        current.append(url)
                        obj.image_urls = current
                        try:
                            self.message_user(request, 'COS未配置或上传失败，已保存到本地媒体', level='warning')
                        except Exception:
                            pass
        super().save_model(request, obj, form, change)

    def _http_get(self, url, params):
        query = urllib.parse.urlencode(params)
        full = url + ('?' + query if query else '')
        with urllib.request.urlopen(full, timeout=5) as resp:
            body = resp.read().decode('utf-8')
            return json.loads(body)

    def _build_sig(self, path: str, params: dict, sk: str) -> str:
        items = sorted([(k, v) for k, v in params.items() if k != 'sig'], key=lambda x: x[0])
        query = urllib.parse.urlencode(items)
        raw = f"{path}?{query}{sk}"
        return hashlib.md5(raw.encode('utf-8')).hexdigest()

    def action_reverse_geocode(self, request, queryset):
        key = getattr(settings, 'TENCENT_MAP_KEY', '') or os.environ.get('TENCENT_MAP_KEY', '')
        success = 0
        failed = 0
        if not key:
            self.message_user(request, '未配置腾讯位置服务Key', level='error')
            return
        for obj in queryset:
            try:
                if obj.lat is None or obj.lng is None:
                    failed += 1
                    continue
                params = {'location': f"{obj.lat},{obj.lng}", 'key': key, 'radius': 1000}
                sig_secret = os.environ.get('TENCENT_MAP_SIG_SECRET', '')
                if sig_secret:
                    params['sig'] = self._build_sig('/ws/geocoder/v1', params, sig_secret)
                data = self._http_get('https://apis.map.qq.com/ws/geocoder/v1/', params)
                if int(data.get('status', -1)) != 0:
                    failed += 1
                    continue
                ad = (data.get('result', {}) or {}).get('ad_info', {})
                obj.city = ad.get('city') or obj.city
                obj.province = ad.get('province') or obj.province
                obj.nation = ad.get('nation') or obj.nation
                obj.save(update_fields=['city','province','nation'])
                success += 1
            except Exception:
                failed += 1
        self.message_user(request, f'逆地理填充完成：成功 {success} 条，失败 {failed} 条')
    action_reverse_geocode.short_description = '逆地理填充位置（选中项）'

    def action_clear_location(self, request, queryset):
        for obj in queryset:
            obj.city = None
            obj.province = None
            obj.nation = None
            obj.lat = None
            obj.lng = None
            obj.save(update_fields=['city','province','nation','lat','lng'])
        self.message_user(request, f'已清除 {queryset.count()} 条位置数据')
    action_clear_location.short_description = '清除位置数据（选中项）'


@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
    list_display = ['tag_id', 'name', 'post_count', 'created_at']
    search_fields = ['name']
    ordering = ['name']
    list_per_page = 20

    def post_count(self, obj):
        return obj.posts.count()
    post_count.short_description = '动态数'


@admin.register(PostLike)
class PostLikeAdmin(admin.ModelAdmin):
    """动态点赞管理"""
    list_display = ['like_id', 'post_link', 'user_link', 'created_at']
    list_filter = ['created_at']
    date_hierarchy = 'created_at'
    search_fields = ['user__username']
    list_per_page = 20
    
    def post_link(self, obj):
        """显示动态链接"""
        return format_html(
            '<a href="/admin/community/post/{}/change/">动态 {}</a>',
            obj.post.post_id, obj.post.post_id
        )
    post_link.short_description = '动态'
    
    def user_link(self, obj):
        """显示用户链接"""
        if obj.user:
            return format_html(
                '<a href="/admin/auth/user/{}/change/">用户 {}</a>',
                obj.user.id, obj.user.username
            )
        return "未设置用户"
    user_link.short_description = '用户'


@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
    """评论管理"""
    list_display = ['comment_id', 'post_link', 'user_link', 'display_content', 'created_at']
    list_filter = ['created_at']
    date_hierarchy = 'created_at'
    search_fields = ['user__username', 'content']
    ordering = ['-created_at']
    list_per_page = 20
    
    def post_link(self, obj):
        """显示动态链接"""
        return format_html(
            '<a href="/admin/community/post/{}/change/">动态 {}</a>',
            obj.post.post_id, obj.post.post_id
        )
    post_link.short_description = '动态'
    
    def user_link(self, obj):
        """显示用户链接"""
        if obj.user:
            return format_html(
                '<a href="/admin/auth/user/{}/change/">用户 {}</a>',
                obj.user.id, obj.user.username
            )
        return "未设置用户"
    user_link.short_description = '用户'
    
    def display_content(self, obj):
        """显示评论内容摘要"""
        content = obj.content
        if len(content) > 50:
            return f"{content[:50]}..."
        return content
    display_content.short_description = '评论内容'


@admin.register(HomeBanner)
class HomeBannerAdmin(admin.ModelAdmin):
    """首页轮播图管理（社区模块）"""
    list_display = ['banner_id', 'preview', 'title', 'slogan_short', 'align', 'show_text', 'is_active', 'order', 'created_at']
    list_filter = ['is_active', 'align', 'created_at']
    search_fields = ['title', 'slogan']
    ordering = ['order', '-created_at']
    list_per_page = 20
    fields = ['image', 'image_url', 'title', 'slogan', 'align', 'show_text', 'title_color', 'slogan_color', 'title_font_size', 'slogan_font_size', 'offset_x', 'offset_y', 'is_active', 'order']

    class Form(forms.ModelForm):
        class Meta:
            model = HomeBanner
            fields = ['image', 'image_url', 'title', 'slogan', 'align', 'show_text', 'title_color', 'slogan_color', 'title_font_size', 'slogan_font_size', 'offset_x', 'offset_y', 'is_active', 'order']
            widgets = {
                'title_color': forms.TextInput(attrs={'type': 'color'}),
                'slogan_color': forms.TextInput(attrs={'type': 'color'}),
            }

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            if not self.instance.pk:
                # 新建时填充默认标题/标语
                self.fields['title'].initial = self.fields['title'].initial or '绿迹'
                self.fields['slogan'].initial = self.fields['slogan'].initial or '让每一步都有环保温度'

    def get_form(self, request, obj=None, **kwargs):
        defaults = {'form': self.Form}
        defaults.update(kwargs)
        return super().get_form(request, obj, **defaults)

    def preview(self, obj):
        url = ''
        try:
            if obj.image:
                url = obj.image.url
            elif obj.image_url:
                url = obj.image_url
        except Exception:
            url = obj.image_url or ''
        return format_html(f'<img src="{url}" style="height:60px;border-radius:8px;object-fit:cover;" />') if url else '无'
    preview.short_description = '预览'

    def slogan_short(self, obj):
        s = obj.slogan or ''
        return s[:20] + ('...' if len(s) > 20 else '')
    slogan_short.short_description = '标语'

    def title_color_box(self, obj):
        c = obj.title_color or '#ffffff'
        return format_html('<span style="display:inline-block;width:16px;height:16px;border-radius:4px;background:{};border:1px solid #ddd;"></span>', c)
    title_color_box.short_description = '标题颜色'

    def slogan_color_box(self, obj):
        c = obj.slogan_color or '#ffffff'
        return format_html('<span style="display:inline-block;width:16px;height:16px;border-radius:4px;background:{};border:1px solid #ddd;"></span>', c)
    slogan_color_box.short_description = '标语颜色'

    def save_model(self, request, obj, form, change):
        uploaded = request.FILES.get('image')
        if uploaded:
            # 使用COS上传；失败时按配置回退本地
            try:
                result = cos_uploader.upload_file(uploaded, file_type='home_banner', user_id=(getattr(request, 'user', None) and request.user.id))
                if result.get('success') and result.get('url'):
                    obj.image = None
                    obj.image_url = result['url']
                else:
                    require_cos = getattr(settings, 'TENCENT_COS_REQUIRE', False)
                    if require_cos:
                        self.message_user(request, 'COS未配置或上传失败：未保存图片', level='error')
                        obj.image = None
                    else:
                        rel_path = default_storage.save(f"home_banners/{uploaded.name}", uploaded)
                        media_url = (getattr(settings, 'MEDIA_URL', '/media/') or '/media/')
                        obj.image = rel_path
                        obj.image_url = request.build_absolute_uri(media_url.rstrip('/') + '/' + rel_path)
                        self.message_user(request, 'COS未配置或上传失败，已保存到本地媒体', level='warning')
            except Exception:
                require_cos = getattr(settings, 'TENCENT_COS_REQUIRE', False)
                if require_cos:
                    self.message_user(request, 'COS上传异常：未保存图片', level='error')
                    obj.image = None
                else:
                    rel_path = default_storage.save(f"home_banners/{uploaded.name}", uploaded)
                    media_url = (getattr(settings, 'MEDIA_URL', '/media/') or '/media/')
                    obj.image = rel_path
                    obj.image_url = request.build_absolute_uri(media_url.rstrip('/') + '/' + rel_path)
                    self.message_user(request, 'COS上传异常，已保存到本地媒体', level='warning')
        super().save_model(request, obj, form, change)

    actions = ['action_set_active', 'action_set_inactive', 'action_show_text_on', 'action_show_text_off']

    def action_set_active(self, request, queryset):
        queryset.update(is_active=True)
        self.message_user(request, '已设为展示')
    action_set_active.short_description = '设为展示'

    def action_set_inactive(self, request, queryset):
        queryset.update(is_active=False)
        self.message_user(request, '已取消展示')
    action_set_inactive.short_description = '取消展示'

    def action_show_text_on(self, request, queryset):
        queryset.update(show_text=True)
        self.message_user(request, '已开启文案显示')
    action_show_text_on.short_description = '开启文案显示'

    def action_show_text_off(self, request, queryset):
        queryset.update(show_text=False)
        self.message_user(request, '已关闭文案显示')
    action_show_text_off.short_description = '关闭文案显示'

